# -*- encoding:utf-8 -*-
import os
import sys
import wave
import librosa
import librosa.display
import logging
import contextlib
import numpy as np
import matplotlib.pyplot as plot
plot.switch_backend('agg')
eps = np.finfo(np.float).eps
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
GLOBAL_VERBOSITY = 10


class LoggingErrorFilter(logging.Filter):
    def filter(self, record):
        # print(record.__dict__.get("args", 0))
        if record.__dict__.get("verbosity", 0) <= GLOBAL_VERBOSITY:
            return True
        return False


handler = logging.StreamHandler(sys.stdout)      # 不要使用logging.basicConfig
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(filename)s:%(lineno)d- %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
filter = LoggingErrorFilter()
logger.addFilter(filter)


def show_melspectrogram(firgure_dir, mels, title='Log-frequency power spectrogram'):
    librosa.display.specshow(mels, x_axis='time', y_axis='mel',
                             sr=44100)
    plot.colorbar()
    plot.title(title)
    plot.tight_layout()
    plot.savefig(firgure_dir)
    plot.close()


def plot_functions(firgure_dir, _num_epochs, _tr_loss, _val_loss, _f1, _er):
    plot.figure()

    plot.subplot(211)
    plot.plot(range(_num_epochs), _tr_loss, label='train loss')
    plot.plot(range(_num_epochs), _val_loss, label='val loss')
    plot.legend()
    plot.grid(True)

    plot.subplot(212)
    plot.plot(range(_num_epochs), _f1, label='f')
    plot.plot(range(_num_epochs), _er, label='er')
    plot.legend()
    plot.grid(True)

    plot.savefig(firgure_dir)
    plot.close()


def my_argmax(input, default=-1):
    '''
    Notes:
        Learn from: https://stackoverflow.com/questions/51318081/numpy-argmax-when-values-are-equal/51341966
    '''
    twomax = np.partition(input, -2)[-2:]
    index = np.where(twomax[0] != twomax[1], np.argmax(input, -1), default)
    return np.asscalar(index)


def get_wav_len(wav_path):
    with contextlib.closing(wave.open(wav_path, 'r')) as f:
        frames = f.getnframes()
        fr = f.getframerate()
        duration = frames / float(fr)
        return duration


def create_folder(_fold_path):
    if not os.path.exists(_fold_path):
        os.makedirs(_fold_path)


def reshape_3Dto2D(A):
    return A.reshape(A.shape[0] * A.shape[1], A.shape[2])


def split_multi_channels(data, num_channels):
    in_shape = data.shape
    if len(in_shape) == 3:
        hop = int(in_shape[2] / num_channels)
        tmp = np.zeros((in_shape[0], num_channels, in_shape[1], hop))
        for i in range(num_channels):
            tmp[:, i, :, :] = data[:, :, i * hop:(i + 1) * hop]
    else:
        print("ERROR: The input should be a 3D matrix but it seems to have dimensions ", in_shape)
        exit()
    return tmp


def split_in_seqs(data, subdivs):
    if len(data.shape) == 1:
        if data.shape[0] % subdivs:
            data = data[:-(data.shape[0] % subdivs), :]
        data = data.reshape((int(data.shape[0] / subdivs), subdivs, 1))
    elif len(data.shape) == 2:
        if data.shape[0] % subdivs:
            data = data[:-(data.shape[0] % subdivs), :]
        data = data.reshape((int(data.shape[0] / subdivs), subdivs, data.shape[1]))
    elif len(data.shape) == 3:
        if data.shape[0] % subdivs:
            data = data[:-(data.shape[0] % subdivs), :, :]
        data = data.reshape((int(data.shape[0] / subdivs), subdivs, data.shape[1], data.shape[2]))
    return data
